#include "stm32f4xx.h"                  // Device header
#include "stm32f4xx_conf.h"
#include "Delay.h"
#include "VREFVerify.h"

/*
 *函数简介:电压检测初始化
 *参数说明:无
 *返回类型:无
 *备注:默认使用ADC3的通道8(PF10)
 *备注:ADC为非连续非扫描独立模式,单通道无DMA,数据右对齐,分辨率为12bits,软件触发
 *备注:在使用前请先校验V_REF
 *备注:ADCCLK=PCLK/ADC_Prescaler预分频值=84MHz/ADC_Prescaler,默认2分频,ADCCLK=42MHz(大约0.024us)
 *备注:转换一次所需时间:T=采样周期+转换周期=(采样周期+分辨率)*ADCCLK,默认T=(3+12)*(1/42MHz)≈0.36us
 */
void VoltageDetection_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3,ENABLE);
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE);//打开时钟
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;//配置为模拟输入
	GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;//默认上拉
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
	GPIO_Init(GPIOF,&GPIO_InitStructure);//初始化PF10
	
	ADC_RegularChannelConfig(ADC3,ADC_Channel_8,1,ADC_SampleTime_3Cycles);//选择规则组输入通道ADC3通道ADC_Channel_8为序列1,采样时间3ADCCLK
	
	ADC_CommonInitTypeDef ADC_CommonInitStructure;
	ADC_CommonInitStructure.ADC_Mode=ADC_Mode_Independent;//独立模式
	ADC_CommonInitStructure.ADC_DMAAccessMode=ADC_DMAAccessMode_Disabled;//不开启DMA
	ADC_CommonInitStructure.ADC_Prescaler=ADC_Prescaler_Div2;//预分频为2
	ADC_CommonInitStructure.ADC_TwoSamplingDelay=ADC_TwoSamplingDelay_5Cycles;//2个采样阶段之间的延迟,在双重或三重交错模式下使用,此处随意设置
	ADC_CommonInit(&ADC_CommonInitStructure);
	
	ADC_InitTypeDef ADC_InitStructure;
	ADC_InitStructure.ADC_ContinuousConvMode=DISABLE;//配置为连续转换
	ADC_InitStructure.ADC_ScanConvMode=DISABLE;//配置为非扫描
	ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;//配置为数据右对齐
	ADC_InitStructure.ADC_NbrOfConversion=1;//通道数1
	ADC_InitStructure.ADC_Resolution=ADC_Resolution_12b;//分辨率为12bits
	ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_Ext_IT11;//外部事件选择,软件触发下此位无意义
	ADC_InitStructure.ADC_ExternalTrigConvEdge=ADC_ExternalTrigConvEdge_None;//配置为软件触发(不使用外部触发)
	ADC_Init(ADC3,&ADC_InitStructure);//初始化ADC3
	
	ADC_Cmd(ADC3,ENABLE);//启动ADC
	Delay_s(1);//等待唤醒
}

/*
 *函数简介:电压检测获取V_BAT
 *参数说明:无
 *返回类型:V_BAT的值
 *备注:采集1000次取平均值,用时t=1000*T=1000*(15/42MHz)≈357.14us
 *备注:根据硬件分压电路,V_ADCIN=V_BAT*22/222
 *备注:根据实际测试,线性回归拟合得到拟合方程:
 *		V_BAT=(V_ADCGet-0.158469)*(1-0.029334)=(ADC_OUT/22*222-0.158469)*(1-0.029334)
 *			 =(sum/1000.0/V_REF*1.2/22*222-0.158469)*(1-0.029334)
 *			 =(sum*0.012109/V_REF-0.158469)*1.030220
 *			 =sum*0.012475/V_REF-0.163258
 */
float VoltageDetection_GetVBAT(void)
{
	uint64_t sum=0;//1000次累计值
	for(uint16_t i=0;i<1000;i++)//采集1000次
	{
		ADC_RegularChannelConfig(ADC3,ADC_Channel_8,1,ADC_SampleTime_3Cycles);//选择规则组输入通道ADC3通道ADC_Channel_8为序列1,采样时间3ADCCLK
		ADC_SoftwareStartConv(ADC3);//软件触发转换开始
		while(ADC_GetFlagStatus(ADC3,ADC_FLAG_EOC)==RESET);//等待转换完成
		sum+=ADC_GetConversionValue(ADC3);//累计
	}
	return sum*0.012475f/V_REF-0.163258f;
}
